package uy.org.softtech.cssuite.entidad.cliente;

import static org.springframework.util.StringUtils.hasText;
import static org.springframework.util.StringUtils.trimWhitespace;
import static uy.org.softtech.cssuite.entidad.Entidad.CLIENTE_NAMESPACE;
import static uy.org.softtech.cssuite.helpers.HelperTextos.URUGUAY;
import static uy.org.softtech.cssuite.helpers.HelperTextos.formatearTelefono;

import java.io.Serializable;
import java.util.Locale;

import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;

import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.map.annotate.JsonRootName;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion;

import uy.org.softtech.cssuite.helpers.HelperTextos;

/**
 * <p>Entidad que representa a una persona como cliente. También mapea la declaración del tipo de dato XML 'persona'.</p>
 * 
 * <p>El siguiente fragmento de esquema especifica el contenido esperado y representado por los atributos de esta clase.</p>
 *  
 * <pre>
 * &lt;xsd:complexType name="persona">
 *  &lt;xsd:all>
 *   &lt;xsd:element name="id" type="xsd:ID"/>
 *   &lt;xsd:element name="apellido" type="{http://cssuite.softtech.org.uy/esquemas/tipos}nombre"/>
 *   &lt;xsd:element name="primerNombre" type="{http://cssuite.softtech.org.uy/esquemas/tipos}nombre"/>
 *   &lt;xsd:element name="bloqueado" type="xsd:boolean"/>
 *   &lt;xsd:element name="segundoNombre" type="{http://cssuite.softtech.org.uy/esquemas/tipos}nombre" minOccurs="0" />
 *   &lt;xsd:element name="correoElectronico" type="{http://cssuite.softtech.org.uy/esquemas/tipos}correo" minOccurs="0"/>
 *   &lt;xsd:element name="telefono" type="{http://cssuite.softtech.org.uy/esquemas/tipos}texto" minOccurs="0"/>
 *   &lt;xsd:element name="celular" type="{http://cssuite.softtech.org.uy/esquemas/tipos}texto" minOccurs="0"/>
 *   &lt;xsd:element name="comentarios" type="{http://cssuite.softtech.org.uy/esquemas/tipos}comentario" minOccurs="0"/>
 *   &lt;xsd:element name="cuentas">
 *    &lt;xsd:complexType>
 *     &lt;xsd:sequence>
 *      xsd:element name="cuenta" type="{http://cssuite.softtech.org.uy/esquemas/entidades}cuenta" maxOccurs="unbounded" />
 *     &lt;/xsd:sequence>
 *    &lt;/xsd:complexType>
 *   &lt;/xsd:element>
 *  &lt;/xsd:all>
 * &lt;/xsd:complexType>
 * 
 * </pre>
 *
 * @author fabian.lobo
 */
@Entity
@DiscriminatorValue("PERSONA")
@JsonRootName(value = "persona")
@JsonSerialize(include = Inclusion.NON_NULL)
@XmlType(name = "persona", namespace = CLIENTE_NAMESPACE, propOrder = {})
public class Persona extends Cliente implements Serializable {

	private static final long serialVersionUID = -2711474938394734237L;
	
	@Column(name = "NOMBRE", length = 25, nullable = false)
	@XmlElement(name = "primerNombre", namespace = CLIENTE_NAMESPACE, required = true)
	private String primerNombre;
	
	@Column(name = "APELLIDO", length = 25, nullable = true)
	@XmlElement(name = "apellido", namespace = CLIENTE_NAMESPACE, required = true)
	private String apellido;

	@Column(name = "SEGUNDO_NOMBRE", length = 25, nullable = true)
	@XmlElement(name = "segundoNombre", namespace = CLIENTE_NAMESPACE, required = false)
	private String segundoNombre;
	
	@Column(name = "CORREO_ELECTRONICO", length = 50, nullable = true)
	@XmlElement(name = "correoElectronico", namespace = CLIENTE_NAMESPACE, required = false)
	private String correoElectronico;
	
	@Column(name = "TELEFONO", length = 25, nullable = true)
	@XmlTransient
	private String telefono;
	
	@Column(name = "CELULAR", length = 25, nullable = true)
	@XmlTransient
	private String celular;
	
	public Persona() {
		setTipo(Tipo.PERSONA);
	}
	
	/*
	 *  GETTERS
	 */
	public String getPrimerNombre() {
		return primerNombre;
	}
	public String getApellido() {
		return apellido;
	}
	public String getSegundoNombre() {
		return segundoNombre;
	}
	public String getCorreoElectronico() {
		return correoElectronico;
	}
	public String getTelefono() {
		return telefono;
	}
	public String getCelular() {
		return celular;
	}
	
	/*
	 *  SETTERS
	 */
	public void setPrimerNombre(String primerNombre) {
		this.primerNombre = primerNombre;
	}
	public void setApellido(String apellido) {
		this.apellido = apellido;
	}
	public void setSegundoNombre(String segundoNombre) {
		this.segundoNombre = segundoNombre;
	}
	public void setCorreoElectronico(String correoElectronico) {
		this.correoElectronico = correoElectronico;
	}
	public void setTelefono(String telefono) {
		this.telefono = telefono;
	}
	public void setCelular(String celular) {
		this.celular = celular;
	}
	
	/*
	 *  CONVERSORES
	 */
	/**
	 * Convierte el número de teléfono fijo a texto
	 * 
	 * @author fabian.lobo
	 * @see HelperTextos#formatearTelefono(String, Locale)
	 */
	@JsonProperty(value = "telefono")
	//@XmlElement(name = "telefono", namespace = CLIENTE_NAMESPACE, required = false)
	public String convierteTelefono() {
		return formatearTelefono(getTelefono(), URUGUAY);
	}
	
	/**
	 * Convierte el número de teléfono celular a texto
	 * 
	 * @author fabian.lobo
	 * @see HelperTextos#formatearTelefono(String, Locale)
	 */
	@JsonProperty(value = "celular")
	//@XmlElement(name = "celular", namespace = CLIENTE_NAMESPACE, required = false)
	public String convierteCelular() {
		return formatearTelefono(getCelular(), URUGUAY);
	}
	
	/**
	 * Convierte los datos de primer nombre + segundo nombre + apellido a un nombre de una sola línea
	 * 
	 * @author fabian.lobo
	 * @see #getPrimerNombre()
	 * @see #getSegundoNombre()
	 * @see #getApellido()
	 */
	public String convierteNombreCompleto() {
		StringBuffer buffer = new StringBuffer();
		buffer.append(trimWhitespace(getPrimerNombre()));
		if(hasText(getSegundoNombre())) {
			buffer.append(" ");
			buffer.append(trimWhitespace(getSegundoNombre()));
		}
		buffer.append(" ");
		buffer.append(trimWhitespace(getApellido()));
		return trimWhitespace(buffer.toString());
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 5;
		result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		Persona otro = (Persona) obj;
		if (getId() != null && otro.getId() != null && getId().equals(otro.getId())) {
			return true;
		}
		return false;
	}

	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append("Persona [");
		builder.append("id=" + getId() + ", ");
		builder.append("primerNombre=" + getPrimerNombre() + ", ");
		builder.append("apellido=" + getApellido() + ", ");		
		builder.append("segundoNombre=" + getSegundoNombre() + ", ");
		builder.append("correoElectronico=" + getCorreoElectronico() + ", ");
		builder.append("telefono=" + convierteTelefono() + ", ");
		builder.append("celular=" + convierteCelular() + ", ");
		builder.append("eliminado=" + isEliminado() + ", ");
		builder.append("bloqueado=" + isBloqueado() + ", ");
		builder.append("comentarios=" + getComentarios());
		builder.append("]");
		return builder.toString();
	}

	@Override
	public String toString(boolean incluirColecciones) {
		StringBuilder result = new StringBuilder(toString());
		
		if(incluirColecciones) {
			int offset = result.length() - 2;
			StringBuilder builder = new StringBuilder(", ");
			builder.append("cuentas=" + getCuentas());
			result.insert(offset, builder.toString());
		}	
				
		return result.toString();
	}

}
